package com.snopy.file;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author snopy
 * @version 1.0.0
 * @classname MultipartUploadParser
 * @description 多部分上传解析器
 * @email 77912204@qq.com
 * @date 2022/03/16 11:47
 */
@Slf4j
public class MultipartUploadParser {
        private Map<String,String> params = new HashMap<>();
        private List<FileItem> files = new ArrayList<>();
        private DiskFileItemFactory fileItemFactory;

        public MultipartUploadParser(HttpServletRequest request, File repository, ServletContext context) throws IOException, FileUploadException {
                if (!repository.exists() && !repository.mkdirs()){
                        throw new IOException("Unable to mkdirs to " + repository.getAbsolutePath());
                }
                fileItemFactory = setupFileItemFactory(repository,context);
                ServletFileUpload upload = new ServletFileUpload(fileItemFactory);
                List<FileItem> formFileItems = upload.parseRequest(request);
                parseFormFields(formFileItems);
                if (files.isEmpty()){
                        log.warn("No files were found when processing the request. Debugging info follows.");
                        writeDebugInfo(request);
                        throw new FileUploadException("No files were found when processing the requst.");
                }else {
                        if (log.isDebugEnabled()) {
                                writeDebugInfo(request);
                        }
                }

        }
        private DiskFileItemFactory setupFileItemFactory(File repository,ServletContext context){
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
                factory.setRepository(repository);

                FileCleaningTracker pTracker = FileCleanerCleanup.getFileCleaningTracker(context);
                factory.setFileCleaningTracker(pTracker);
                return factory;
        }
        private void writeDebugInfo(HttpServletRequest request)
        {
                log.debug("-- POST HEADERS --");
                for (Object header : Collections.list(request.getHeaderNames()))
                {
                        log.debug("{}: {}", header, request.getHeader(header.toString()));
                }

                log.debug("-- POST PARAMS --");
                for (String key : params.keySet())
                {
                        log.debug("{}: {}", key, params.get(key));
                }
        }

        private void parseFormFields(List<FileItem> items){
                for (FileItem item : items){
                        if (item.isFormField()){
                                String key = item.getFieldName();
                                String value = item.getString();
                                if (StringUtils.isNotBlank(key)){
                                        params.put(key,StringUtils.defaultString(value));
                                }
                        }else {
                                files.add(item);
                        }
                }
        }

        public Map<String, String> getParams() {
                return params;
        }
}
